package ar.uba.fi.algo3.tp3.modelo;

import java.util.Random;

abstract public class Fantasma extends Personaje {
    private boolean mortal;
    private int tiempoHastaSerInmortal;
    private boolean enRuta;
    private Ruta ruta;
    private int antiguedadComportamiento;
    private int nivel;
    private boolean muerto;
    private int tiempoHastaRenacer;

    public Fantasma(Mapa mapa, int nivel) {
        super(mapa.getCasaFantasmas().getX(), mapa.getCasaFantasmas().getY(), mapa);
        mortal = false;
        tiempoHastaSerInmortal = 0;
        enRuta = false;
        antiguedadComportamiento = 0;
        this.nivel = mapa.getNivel();
        this.muerto = false;
        this.tiempoHastaRenacer = 0;
    }

    private void seguirRuta() {

        if (ruta == null || ruta.vacia()) {
            enRuta = false;
        } else {
            PuntoRuta primero = ruta.getPrimero();
            if (x == primero.getX() && y == primero.getY()) {
                ruta.puntoCumplido();
            }
            if (!ruta.vacia()) {
                PuntoRuta siguientePunto = ruta.getPrimero();
                if (siguientePunto.getX() > x) {
                    this.direccionFutura = Direccion.DERECHA;
                } else if (siguientePunto.getX() < x) {
                    this.direccionFutura = Direccion.IZQUIERDA;
                } else if (siguientePunto.getY() > y) {
                    this.direccionFutura = Direccion.ABAJO;
                } else if (siguientePunto.getY() < y) {
                    this.direccionFutura = Direccion.ARRIBA;
                }
            }
        }
    }
    
    public void setTiempoHastaRenacer(int tiempo){
    	tiempoHastaRenacer = tiempo;
    }

    public void setRuta(Ruta r) {
        this.ruta = r;
        this.enRuta = true;
    }

    protected void pensar(int xDestino, int yDestino) {

        antiguedadComportamiento++;
        if (enRuta) {
            seguirRuta();
        }

        if (!enRuta) {
            if (Math.random() < 0.1 || !mapa.sePuedeIrA(x, y, direccion, velocidad)) {
                Random random = new Random();
                Direccion direccionNueva = null;
                do {
                    direccionNueva = Direccion.values()[random.nextInt(Direccion.values().length)];
                } while (direccionNueva == direccion.getOpuesta());

                direccionFutura = direccionNueva;
            }
        }

        if (antiguedadComportamiento > 150) {
            antiguedadComportamiento = 0;
            if (Math.random() > this.getFactorAzar()) {
                Ruta r = BuscadorDeCaminos.buscarCamino(mapa, x, y, xDestino, yDestino);
                this.setRuta(r);
            } else {
                enRuta = false;
            }
        }
    }

    protected void comportamientoElusivo(){
    	int posRefX = 230 - mapa.getPacman().getX();
    	int posRefY = 230 - mapa.getPacman().getY();
    	moverAdyacente(posRefX,posRefY);
        pensar(230 + posRefX,230 + posRefY);
    }
    
    protected void moverAdyacente(int x, int y){
    	if(!mapa.sePuedeIrA(x,y,Direccion.DERECHA,0)){
    		if(mapa.sePuedeIrA(x+30, y, Direccion.DERECHA, 0))
    			x = x+30;
    		if(mapa.sePuedeIrA(x, y+30, Direccion.DERECHA, 0))
    			y = y+30;
    		if(mapa.sePuedeIrA(x-30,y,Direccion.DERECHA,0))
    			x = x-30;
    		if(mapa.sePuedeIrA(x,y-30,Direccion.DERECHA,0))
    			y = y-30;
    	}
    }
    
    public Direccion getDireccion(){
    	return this.direccion;
    }
    
    public Direccion getDireccionFutura(){
    	return this.direccionFutura;
    }
    
    public int getVelocidad(){
    	return this.velocidad;
    }
    
    public boolean estaMuerto() {
        return this.muerto;
    }

    abstract protected double getFactorAzar();

    public void vivir() {
        if (muerto) {
            if (tiempoHastaRenacer <= 0) {
                this.muerto = false;
            }
            tiempoHastaRenacer -= 1;
            direccionFutura = Direccion.ABAJO;
        } else {
            if (mortal) {
                velocidad = 3;
                comportamientoElusivo();
            } else {
                velocidad = 3 + 3 * Math.round(nivel / 10);
            }
            /*if(comportamientoAlterado){
            	comportamientoElusivo();
            }*/
            verSiComeAPacman();
            revisarInmortalidad();
            super.vivir();
        }
    }

    public boolean esMortal() {
        return mortal;
    }
    

    private void revisarInmortalidad() {
        if (mortal) {
            tiempoHastaSerInmortal--;
            if (tiempoHastaSerInmortal == 0) {
                mortal = false;
            }
        }
    }

    public void morir() {
        if (mortal) {
            x = mapa.getCasaFantasmas().getX();
            y = mapa.getCasaFantasmas().getY();
            enRuta = false;
            antiguedadComportamiento = 0;
            mortal = false;
            muerto = true;
            tiempoHastaRenacer = (int)Math.round(10 + Math.random() * 20);
            Partida.getInstance().sumarPuntosFantasma();
        }
    }

    private void verSiComeAPacman() {
        if (mapa.hayPacman(x, y) != null) {
            Pacman pacman = mapa.getPacman();
            pacman.morir();
        }
    }

    public void setMortal(boolean mortal) {
        this.mortal = mortal;
        tiempoHastaSerInmortal = 180-Partida.getInstance().getInfoPartida().getNivel()*8;
        ruta = null;
    }

    @Override
    public boolean equals(Object otroFantasma) {
        Fantasma fantasma = (Fantasma)otroFantasma;
        boolean iguales = true;
        if(fantasma.esMortal() != this.esMortal())
            return false;
        else if(fantasma.tiempoHastaRenacer != this.tiempoHastaRenacer)
            return false;
        else if(fantasma.tiempoHastaSerInmortal != this.tiempoHastaSerInmortal)
            return false;
        else if(fantasma.enRuta != this.enRuta)
            return false;
        else if(fantasma.antiguedadComportamiento != this.antiguedadComportamiento)
            return false;
        else if(fantasma.nivel != this.nivel)
            return false;
        else if(fantasma.muerto != this.muerto)
            return false;
        else
            return true;
    }
}